#include "Game.h"
#include "DXUtil.h"
#include <d3dx9.h>
#include <d3d9.h>
#include <iostream>
#include "ModelPrimitive.h"
#include "AnimChangeOverTime.h"
#include "Sphere.h"
#include "PhysicsPlane.h"


void Game::Initialize(LPDIRECT3DDEVICE9 d3ddev, LPDIRECT3D9 myDirect3D)
{
	mPhysWorld = new PhysicsWorld();
	mTotalTime = 0.0f;
	D3DXMatrixIdentity(&mIdentity);
	IniScene(d3ddev);
	LoadContent(d3ddev);
}

void Game::Update(LPDIRECT3DDEVICE9 d3ddev, double pElapsedTime) 
{
	mTotalTime += pElapsedTime;	
	/*
	for(int i = 0; i < mModels.size(); i++ )
	{
		mModels[i]->Update(d3ddev,pElapsedTime, mTotalTime);

		if(mModels[i]->GetName().compare("Airplane") == 0){
		//	mCamera->SetLookAt(*(mModels[i]->GetPos()));
	}
		
		
		if(mModels[i]->GetName().compare("Airplane") == 0){
			if(mModels[i]->GetPos()->y > 50){
				mModels[i]->GetPos()->y = -50.0f;
				mModels[i]->GetPos()->x = -50.0f;
			}
		}
		*/
		mPhysWorld->Update(pElapsedTime/1000.0f);
	//}

	for(int i = 0; i < mLights.size(); i++ )
	{
		if(mLights[i]->GetOn()){	
		    d3ddev->LightEnable(mLights[i]->GetLightNumber(), true);    // turn on light #0   
		}
		else if(mLights[i]->GetLightNumber() < 0 ){
			d3ddev->LightEnable(mLights[i]->GetLightNumber(),false);
		}
	}
}

D3DVECTOR* Game::DetermineEllipseTangent(D3DVECTOR* circle,D3DVECTOR* point )
{
     // This is just an implementation of the equation in the tutorial. All we need is a vector
     // giving the direction of the tangent, hence we only pay attention to the final terms.
 
     // The variable t is simply a parameter to the equation. We are only paying attention to
     // the final terms, and since they give the slope (i.e., the direction of the tangent), we
     // let t = 1.
 
   //  D3DVECTOR tangent = new D3DVECTOR();
    // tangent.x = point->x - (Ellipse->z* point->y)/Ellipse->z;
     //tangent.y = point->y + (Ellipse->z*point->x)/Ellipse->z;
	return NULL;
   //  return &tangent;     
}

void Game::IniScene(LPDIRECT3DDEVICE9 d3ddev){

	if(input.compare("") != 0)
	{
		vector<Sphere*> balls;
		ifstream fp_in;  // declarations of streams fp_in and fp_out
		fp_in.open(input.c_str(), ios::in);    // open the streams
		float mass = 0.0f;
		while(!fp_in.eof() && fp_in.good())
		{
			vector<string> tokens;
			string test;
			getline(fp_in, test);
			Tokenize(test, tokens);
			if(tokens[0].compare("ball") == 0)
			{
				float radius = 0.0f;
				if(tokens.size() == 5)
				{
					radius = atof(tokens[4].c_str());
				}
				else
				{
					radius = .08f;
				}
				Sphere* ball = new Sphere(d3ddev, D3DXVECTOR3(atof(tokens[1].c_str()),atof(tokens[2].c_str()),atof(tokens[3].c_str())), radius);
				balls.push_back(ball);
			}
			if(tokens[0].compare("force") == 0)
			{
				D3DXVECTOR3* velocity = new D3DXVECTOR3(atof(tokens[1].c_str()),atof(tokens[2].c_str()),atof(tokens[3].c_str()));
				float mass = balls[0]->GetPhysics()->GetMass();
				*velocity = *velocity / mass;
				balls[0]->GetPhysics()->SetVelocity(velocity);
				balls[0]->GetPhysics()->Update(0.0f);
				balls[0]->GetPhysics()->Finalize(0);
			}
			if(tokens[0].compare("friction") == 0)
			{
				mPhysWorld->mew = atof(tokens[1].c_str());
			}
			if(tokens[0].compare("rest") == 0)
			{
				mPhysWorld->rest = atof(tokens[1].c_str());
			}
			if(tokens[0].compare("mass") == 0)
			{
				mass = atof(tokens[1].c_str());
			}
		}

		fp_in.close();

		for(int i = 0; i < balls.size(); i++)
		{
			balls[i]->GetPhysics()->SetMass(mass);
			mModels.push_back(balls[i]);
			mPhysWorld->AddModel(balls[i]);
		}
	}

	Sphere* mSphere = new Sphere(d3ddev, D3DXVECTOR3(0,0.f,0), 0.08f);
	mSphere->GetMaterial()->Ambient.r = 0.3f;
	mSphere->GetMaterial()->Ambient.g = 0.3f;
	mSphere->GetMaterial()->Ambient.b = 0.3f;


	Sphere* mSphere2 = new Sphere(d3ddev, D3DXVECTOR3(-0.1f,0.0f,-0.3f), .08f);
	mSphere2->GetMaterial()->Ambient.r = 0.3f;
	mSphere2->GetMaterial()->Ambient.g = 1.0f;
	mSphere2->GetMaterial()->Ambient.b = 0.3f;
	mSphere2->GetPhysics()->SetMass(1.0f);

	ModelPrimitive* mPlane = new ModelPrimitive();
	mPlane->SetBox(d3ddev,1.298f, 0.001f, 2.438f,NULL);
	mPlane->SetPos(new D3DXVECTOR3(0.0f,-0.08f,0.0f));
	mPlane->GetMaterial()->Ambient.r = 0.3f;
	mPlane->GetMaterial()->Ambient.g = 0.3f;
	mPlane->GetMaterial()->Ambient.b = 0.3f;
	mPlane->GetMaterial()->Diffuse.r = 0.0f;
	mPlane->GetMaterial()->Diffuse.g = .5f;
	mPlane->GetMaterial()->Diffuse.b = 0.0f;

	PhysicsPlane* side1 = new PhysicsPlane(d3ddev, D3DXVECTOR3((1.298f/2),0,0), .01f, .1f, 2.438f, new D3DXVECTOR3(-1,0,0));
	side1->GetMaterial()->Ambient.r = 0.3f;
	side1->GetMaterial()->Ambient.g = 0.3f;
	side1->GetMaterial()->Ambient.b = 0.3f;
	side1->GetMaterial()->Diffuse.r = 0.0f;
	side1->GetMaterial()->Diffuse.g = 0.5f;
	side1->GetMaterial()->Diffuse.b = 0.0f;
	//side1->SetNormal(&D3DXVECTOR3(-1,0,0));

	PhysicsPlane* side2 = new PhysicsPlane(d3ddev, D3DXVECTOR3(-(1.298f/2),0,0), .01f, .1f, 2.438f, new D3DXVECTOR3(1,0,0));
	side2->GetMaterial()->Ambient.r = 0.3f;
	side2->GetMaterial()->Ambient.g = 0.3f;
	side2->GetMaterial()->Ambient.b = 0.3f;
	side2->GetMaterial()->Diffuse.r = 0.0f;
	side2->GetMaterial()->Diffuse.g = 0.5f;
	side2->GetMaterial()->Diffuse.b = 0.0f;
	//side2->SetNormal(&D3DXVECTOR3(-1,0,0));
	
	PhysicsPlane* side3 = new PhysicsPlane(d3ddev, D3DXVECTOR3(0,0,(2.438/2)), 1.298f, .1f, .01f, new D3DXVECTOR3(0,0,-1));
	side3->GetMaterial()->Ambient.r = 0.3f;
	side3->GetMaterial()->Ambient.g = 0.3f;
	side3->GetMaterial()->Ambient.b = 0.3f;
	side3->GetMaterial()->Diffuse.r = 0.0f;
	side3->GetMaterial()->Diffuse.g = 0.5f;
	side3->GetMaterial()->Diffuse.b = 0.0f;
	//side3->SetNormal(&D3DXVECTOR3(-1,0,0));

	PhysicsPlane* side4 = new PhysicsPlane(d3ddev, D3DXVECTOR3(0,0,-(2.438/2)), 1.298f, .1f, .01f, new D3DXVECTOR3(0,0,1));
	side4->GetMaterial()->Ambient.r = 0.3f;
	side4->GetMaterial()->Ambient.g = 0.3f;
	side4->GetMaterial()->Ambient.b = 0.3f;
	side4->GetMaterial()->Diffuse.r = 0.0f;
	side4->GetMaterial()->Diffuse.g = 0.5f;
	side4->GetMaterial()->Diffuse.b = 0.0f;

	/*mModels.push_back(mSphere);
	mModels.push_back(mSphere2);*/
	//mModels.push_back(mPlane);
	mModels.push_back(side1);
	mModels.push_back(side2);
	mModels.push_back(side3);
	mModels.push_back(side4);

	//mPhysWorld->AddModel(mSphere);
	//mPhysWorld->AddModel(mSphere2);
	////mPhysWorld->AddModel(mPlane);
	mPhysWorld->AddModel(side1);
	mPhysWorld->AddModel(side2);
	mPhysWorld->AddModel(side3);
	mPhysWorld->AddModel(side4);


	//mSphere->GetPhysics()->ApplyForces(new D3DXVECTOR3(2,0,0),NULL);
//	mSphere->GetPhysics() -> SetVelocity(new D3DXVECTOR3(0.0f,0.0f,0));
	//mSphere->GetPhysics()-> SetVelocity(new D3DXVECTOR3(0.0f,0.0f,-1.0f));
	////mSphere->GetPhysics()->SetAcceleration(new D3DXVECTOR3(0,0,0));
	//mSphere->GetPhysics()-> SetMass(1.25f);
	//mSphere->GetPhysics()-> Update(0);
	//mSphere->GetPhysics()-> Finalize(0);

	mCamera = new Camera();

	D3DVIEWPORT9 view;
	d3ddev->GetViewport( &view);
	mCamera->SetAspectRatio(((float)(view.Width))/view.Height);
	
	mCamera->GetEyePos()->x = -.5f;
	mCamera->GetEyePos()->y = 2.0f;
	mCamera->GetEyePos()->z = 1.5f;

	mCamera->SetLookAt(D3DXVECTOR3(0,0,0));

	mCamera->SetNearPlane(.0001f);

	mCamera->SetFarPlane(100000.0f);
		
	
	

	Light* mLight= new Light();

	/*mLight->GetDirection()->x = 0.0f;
	mLight->GetDirection()->y = 1.0f;
	mLight->GetDirection()->z = 0.0f;*/

	mLight->SetDirection(&D3DXVECTOR3(0,-1,-1));
	

	mLight->SetOn(true);
	mLights.push_back(mLight);

	for(int i = 0; i < mLights.size(); i++ )
	{
		mLights[i]->SetLightNumber(i);
		d3ddev->SetLight(mLights[i]->GetLightNumber()
						, mLight->GetD3DLight()); 
	}		
}

void Game::LoadContent(LPDIRECT3DDEVICE9 d3ddev){
	for(int i = 0; i < mModels.size(); i++ )
	{
		//mModels[i]->LoadContent(d3ddev);
	}
}

//Draws the list of models
void Game::Draw(LPDIRECT3DDEVICE9 d3ddev){
	
	d3ddev->Clear(0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(75, 200, 100), 1.0f, 0); // clear frame
	d3ddev->BeginScene();

	//Set Camera
	d3ddev->SetTransform(D3DTS_VIEW, mCamera->GetViewMatrix());    // set the view transform to matView

    // set the projection transform
    d3ddev->SetTransform(D3DTS_PROJECTION, mCamera->GetProjectionMatrix());    // set the projection
	
	//mMesh->Draw(d3ddev);
	//Draw Models
	for(int i = 0; i < mModels.size(); i++ )
	{
		d3ddev->SetTransform(D3DTS_WORLD, &mIdentity);
		mModels[i]->Draw(d3ddev);
	}
	
	d3ddev->EndScene();
}

void Game::Release(){
	for(int i = 0; i < mModels.size(); i++ )
	{
		mModels[i]->Release();
	}

}
